home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
libs
/
shadowlib.lha
/
shadow
/
Docs
/
ShadowLibraryFuncs.doc
< prev
next >
Wrap
Text File
|
1992-11-13
|
137KB
|
4,374 lines
Shadow.library Documentation
Library Version 5.0
By David Navas
Updated: 13 Nov 1992
Copyright © 1992 by David Navas
All Rights Reserved
NAME
AddAttributes -- Create the attribute table for a class.
SYNOPSIS
result = AddAttributes( class, tags, num, offset )
d0 a0 a1 d0 d1
FUNCTION
This function creates the array of Attribute structures that are
described both by the tags and by the superclass of the passed
class.
This is a low-level function which is used by the provided
Metas. You should not have to call this function yourself,
however you can if for some reason you feel compelled to do
so.
Note that the array of Attributes, as stored in the class'
AttributeTable, includes all of the attributes, both as described
in the tags, AND as described in the superclass. If you're
looking for an attribute description, you don't need to look at
any superclass to find it.
It is unfortunate that, unlike METHODs, attributes defined in the
superclass have to copied to all subclasses. In reality, only
the WATCHED attributes NEED to be copied, however this
involves an increased level of complexity which has yet to be
implemented, and so it remains -- 16bytes per attribute.... sigh.
There are some benefits, however. Multiple inheritence of
attributes is easy. It's unimplemented, but it's a hop-skip-jump
away....
After forming the AttibuteTable, the attributes are qsort'ed by the
attribute name, for fast attribute lookup. Note that this is a
sorting by the System String's address, not by the string's value.
For more information about system Strings, see the UseString()
function.
INPUTS
META class; - the new class for which to build an
AttributeTable.
Function returns NULL if NULL class is
passed.
ATTRIBUTE_TAG tags[]; - the (optional) new atributes to
include.
long num; - the number of additional attributes
from the class' superClass -- as
returned by PrepareAttrTags().
ULONG offset; - the offset at which the next attribute
will reside. This is usually the
size of the class' superClass.
OUTPUTS
long result; - result code (should be a BOOL, oh well.)
Specifies whether the AttributeTable was successfully built. NULL
indicates an error.
RESULT
The specified class' AttributeTable is initialized.
BUGS
none known.
NOTES
Attributes are guaranteed to be arranged according to the order in
which they are specified in the tags[]. This allows you to build
a fixed structure over several attributes, or even over the whole
object definition. [Internally this is done for all of the classes,
with the exception of DIRECTOR_CLASS.]
EG:
The following:
ATTR_1 struct MyAttr1
ATTR_2 struct MyAttr2
ATTR_3 struct MyAttr3
Is basically the same as:
ATTR_1 struct {
struct MyAttr1
struct MyAttr2
struct MyAttr3
};
SEE ALSO
PrepareAttrTags()
CopyDefaultAttributes()
FreeAttributes()
FindAttribute()
FindAttrDefn()
UseString()
NAME
AddAutoResource -- Adds an automatically freed resource to a process.
SYNOPSIS
result = AddAutoResource( task, resource, key)
d0 a0 d0 a1
FUNCTION
This function adds the specified resource to the optionally
specified task (defaults to current task) using the specified
key.
These resources are kept on the PROCESS_CLASS' ATTR_RESOURCETREE,
and are automatically freed (via a METH_REMOVE, and a
DropObject()) whenever:
a) The process receives a METH_REMOVE
b) The process receives a METH_DESTROY
c) The process receives a METH_PROC_DISASSOCIATE
d) A program inside of RemoveCurrentProgram() receives a ^C
e) The default thread-start function inside of SHADOW (after
returning from the METH_PROC_HANDLER method) receives a ^C.
It is important to note that the resource is TRANSFERRED to
(swallowed by) the ATTR_RESOURCETREE. So you no longer own an
object pointer to the resource you passed to AddAutoResource().
If this is a problem you can do:
AddAutoResource(NULL, UseObject(resource), MYNAME)
.
.
<code referencing resource>
.
.
DropObject(resource)
<continue processing, no longer have pointer to resource>
.
.
INPUTS
OBJECT task; - The optional task object that performs
the auto-tracking. If not specified,
assumes current taskObject.
OBJECT resource; - The object to auto-track.
char *key; - The name of the resource. Resources
without names (key == NULL) are stored
by their addresses. Name addresses of
0-255 are reserved for priority freeing.
Resources are freed in INCREASING
key order. Obviously, you can't
use AddAutoResource() to add a
resource at priority zero, as then the
resource would be added at the address
of the resource (NULL == 0).
OUTPUTS
BOOL result; - result code
Specifies whether the resource was added correctly. If it was not,
the resource is sent a METH_REMOVE, is dropped, and a FALSE value
is returned to indicate an error.
If the resource was NULL, then this function returns FALSE
Otherwise returns TRUE
RESULT
The resource is now auto-tracked by the indicated process.
BUGS
none known.
NOTES
SEE ALSO
RemoveAutoResource()
DropObject()
UseObject()
NAME
AddClassWatcher -- Adds a watcher to the given class.
SYNOPSIS
result = AddClassWatcher( watchName, director, pri, name, class )
d0 a0 a1 d2 d0 d1
FUNCTION
This function will add the director to the class' attribute's
watching SList at the given priority with the given name.
This is a low-level function. You should use the provided
DIRECTOR_CLASS methods instead and ask specifically for a
class watcher. Example is in browser.c -- GlobalDirector....
Or see the inluded ShadowLibraryMethods.doc for more details
INPUTS
char *watchName; - the attribute name to watch
OBJECT director; - the director to add to the attribute
watching SList.
long pri; - the priority to add the watcher as.
char *name; - the name of the watcher.
META class; - the class to add the watcher to.
OUTPUTS
BOOL result; - result code
The result code is a boolean indicating the success or failure of
the function call. A zero value indicates that an error occured.
RESULT
The director is added to the class' attribute's watch list.
BUGS
none known.
NOTES
SEE ALSO
AddWatcherNode()
RemoveWatcherNode()
RemoveClassWatcher()
NAME
AddMethods -- initializes a class' method table
SYNOPSIS
result = AddMethods( class, tags )
d0 a0 a1
FUNCTION
This function creates the array of MethodHandler structures that are
described both by the tags.
This is a low-level function which is used by the provided
Metas. You should not have to call this function yourself,
however you can if for some reason you feel compelled to do
so.
Note that the array of MethodHandlers, as stored in the class'
MethodTable, includes only those methods described in the tags
field. Unlike attributes, the superclass' methods are NOT
copied down to the newly defined class.
While creating the MethodHandlers, the passed procObject and
defnObject are UseObject()'d, ensuring that the destination process
and the defining process hang around until the class referencing the
methods goes away.
After forming the MethodTable, the methods are qsort'ed by the
method name, for fast method lookup. Note that this is a
sorting by the System String's address, not by the string's value.
INPUTS
META class; - required class to add the methods to.
METHOD_TAG tags[]; - the (optional and NULL-terminated) array
of MethodTag elements.
OUTPUTS
int result; - result code
The result code is an integer indicating the success or failure of
the function call. A zero value indicates that an error occured.
RESULT
The class' verbs field is initialized.
BUGS
none known.
NOTES
SEE ALSO
DSM() DoShadow() [ShadowLibFuncs.doc]
InvalidateCache()
SetMethodArgs()
DestroyMethodTable()
FindMethodHandle()
BlockMethod()
RemoveAllPatches()
SetupMethodTags()
NAME
AddSListNode -- Adds a node to a prioritized singly linked list.
SYNOPSIS
result = AddSListNode( list, object, pri, name )
d0 a0 a1 d0 d1
FUNCTION
This function adds an object into a singly linked list with the
given name at the given priority (list is ordered by
priority).
INPUTS
SList *list; - a pointer to the list to which to add
the object.
OBJECT object; - the object to add.
long pri; - the priority
char *name; - the name to add it as.
OUTPUTS
BOOL result; - result code
The result code is an integer indicating the success or failure of
the function call. A zero value indicates that an error occured.
Lists of equal priorities are treated as LIFOs.
RESULT
The list has one more node on it -- the passed object.
BUGS
none known.
NOTES
SEE ALSO
FindNodePriInSList() AddWatchedSListNode()
RemoveSListNode() RemoveWatchedSListNode()
NAME
AddTreeNode -- adds an object into binary tree.
SYNOPSIS
result = AddTreeNode( bt, object, key)
d0 a0 a1 d0
FUNCTION
This function will add the object into the binary tree sorted on
the key provided.
The object is Used() by the UseObject() call when successfully
placed in the binary tree.
Any number of objects may exist in any number of binary trees.
There is no restriction on how many trees an object can be
placed, nor in how many times an object can reside in a binary
tree (as there is with Exec lists).
In addition, unlike many AVLTree implementation, objects
inserted with the same key are handled correctly.
INPUTS
AVLTREE *bt; - a pointer to the root of the binary tree.
OBJECT object; - the object to add into the tree.
ULONG key; - the key value to insert on.
OUTPUTS
BOOL result; - result code
zero on failure. (Couldn't allocate binary node)
RESULT
Object is added into binary tree.
BUGS
NOne known.
NOTES
Uses AVL trees. Do not depend on order of insertion
on duplicate keys. (Duplicate keys do work, though.)
Remember that the keys are sorted unsigned, not signed.
SEE ALSO
UseObject()
AddTreeStringNode() AddWatchedTreeNode()
FindTreeNode() AddWatchedTreeStringNode()
FreeTreeAllNodes() RemoveWatchedTreeNode()
RecurseTree() RemoveWatchedTreeStringNode()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
AddTreeStringNode -- add an object to an AVLTREE keyed on a string.
SYNOPSIS
result = AddTreeStringNode( bt, object, name )
d0 a0 a1 d1
FUNCTION
This function will add the object into the binary tree sorted on
the name provided.
The object is Used by the UseObject() call when successfully placed
in the binary tree.
The name uses the UseString and DropString conventions
for system strings. The address of that string then
determines the order the binary tree is sorted in. It
is NOT sorted by the string itself, sorry.
INPUTS
AVLTREE *bt; - a pointer to the root of the binary tree.
OBJECT object; - the object to add into the tree.
char *name; - the name to insert on.
OUTPUTS
BOOL result; - result code
zero on failure. (Couldn't allocate binary node, or system string)
RESULT
The object is added into the binary tree sorted on the address of
the system string that is uniquely created on the passed name.
BUGS
none known.
NOTES
Yes, the third parameter is d1, not d0
No, the binary tree is not sorted on the actual string, but on the
address of the associated system string.
SEE ALSO
UseObject()
DropString()/UseString()
AddTreeNode() AddWatchedTreeNode()
FindTreeNode() AddWatchedTreeStringNode()
FreeTreeAllNodes() RemoveWatchedTreeNode()
RecurseTree() RemoveWatchedTreeStringNode()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
AddWatchedSListNode -- Adds a node to a watched, prioritized singly-
linked list.
SYNOPSIS
result = AddWatchedSListNode( list, object, pri, name )
d0 a0 a1 d0 d1
FUNCTION
This function adds an object into a watched, singly-linked list with
the given name at the given priority (list is ordered by priority).
If any parties are interested, WatcherDispatch is called with
W_INSERT_NODE for the flag paramter.
INPUTS
W_SLIST list; - a pointer to the list to which to add
the object.
OBJECT object; - the object to add.
long pri; - the priority
char *name; - the name to add it as.
OUTPUTS
BOOL result; - result code
The result code is an integer indicating the success or failure of
the function call. A zero value indicates that an error occured.
RESULT
The list has one more node on it -- the passed object.
BUGS
none known.
NOTES
SEE ALSO
AddSListNode()
FindNodePriInSList()
RemoveSListNode() RemoveWatchedSListNode()
NAME
AddWatchedTreeNode -- adds an object into watched binary tree
SYNOPSIS
result = AddWatchedTreeNode( bt, object, key)
d0 a0 a1 d0
FUNCTION
This function will add the object into the watched binary tree
sorted on the key provided.
The object is Used() by the UseObject() call when successfully
placed in the binary tree.
Any number of objects may exist in any number of binary trees.
There is no restriction on how many trees an object can be
placed (as there is on Exec lists).
If any parties are interested, WatcherDispatch is called with
W_INSERT_NODE for the flag parameter.
INPUTS
W_AVLTREE bt; - a pointer to the root of the watched
binary tree.
OBJECT object; - the object to add into the tree.
ULONG key; - the key value to insert on.
OUTPUTS
BOOL result; - result code
zero on failure. (Couldn't allocate binary node)
RESULT
Object is added into binary tree.
BUGS
none known.
NOTES
Uses AVL trees. Do not depend on order of insertion
on duplicate keys. (Duplicate keys do work, though.)
Remember that the keys are sorted unsigned, not signed.
SEE ALSO
UseObject()
AddTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode()
FreeTreeAllNodes()
RecurseTree()
RemoveTreeNode() RemoveWatchedTreeNode()
RemoveTreeStringNode() RemoveWatchedTreeStringNode()
NAME
AddWatchedTreeStringNode -- add an object to a watched AVLTREE,
keyed on a string.
SYNOPSIS
result = AddWatchedTreeStringNode( bt, object, name )
d0 a0 a1 d0
FUNCTION
This function will add the object into the watched binary tree
sorted on the name provided.
The object is Used by the UseObject() call when successfully placed
in the binary tree.
The name uses the UseString and DropString conventions
for system strings. The address of that string then
determines the order the binary tree is sorted in. It
is NOT sorted by the string itself, sorry.
If any parties are interested, WatcherDispatch is called with
W_INSERT_NODE for the flag parameter.
INPUTS
W_AVLTREE bt; - a pointer to the root of the watched
binary tree.
OBJECT object; - the object to add into the tree.
char *name; - the name to insert on.
OUTPUTS
BOOL result; - result code
zero on failure. (Couldn't allocate binary node, or system string)
RESULT
The object is added into the binary tree sorted on the address of
the system string that is uniquely created on the passed name.
BUGS
none known.
NOTES
No, the binary tree is not sorted on the actual string, but on the
address of the associated system string.
SEE ALSO
UseObject()
DropString()/UseString()
AddTreeNode() AddWatchedTreeNode()
AddWatchedTreeStringNode()
FindTreeNode()
FreeTreeAllNodes()
RecurseTree()
RemoveTreeNode() RemoveWatchedTreeNode()
RemoveTreeStringNode() RemoveWatchedTreeStringNode()
NAME
AddWatcherNode -- Adds a watcher to the watched variable
SYNOPSIS
result = AddWatcherNode( wv, node, pri, name )
d0 a0 a1 d0 d1
FUNCTION
This function will add a watcher object (sometimes referred to
as a 'director') into the WatchedVariable wv.
This is a low-level routine. You should use the provided
DIRECTOR_CLASS method. See browser.c for some examples, or the
included ShadowLibMethods.doc for more details.
If any parties are interested, WatcherDispatch is called with
W_INSERT_WATCHER for the flag parameter.
INPUTS
W_VALUE wv; - the watched variable to watch
OBJECT node; - the director to add to the watch list.
long pri; - the priority to add the watcher as.
char *name; - the name of the watcher.
OUTPUTS
BOOL result; - result code
The result code is a boolean indicating the success or failure of
the function call. A zero value indicates that an error occured.
RESULT
The director is added to the watch list.
BUGS
none known.
NOTES
SEE ALSO
RemoveWatcherNode()
AddClassWatcher()
RemoveClassWatcher()
NAME
AllocateItem -- Allocates an item from a MemoryList
SYNOPSIS
element = AllocateItem( list )
d0 a0
FUNCTION
Allocates an element from the list.
The element will NOT be zeroed out, and may contain data from the
last time that element was used.
Elements are allocated 32 at a time via the allocfunc() that was
passed to the InitTable() function. AllocateItem() doles out
these elements one by one, automatically calling allocfunc()
when necessary (ie: when it needs another 32 elements because it
has no more free elements).
INPUTS
SEMLIST list; - the list to allocate from.
OUTPUTS
void *element; - element that is allocated.
As with any allocation function, this function can return NULL for
a failure to allocate memory.
RESULT
One item is allocated on the Memorylist
BUGS
none known.
NOTES
The memory returned is NOT zeroed.
SEE ALSO
InitTable()
FreeTable()
FreeItem()
NAME
BindSuperWatchers -- copies all watchers on the superClass' watched
attributes to the subclass.
SYNOPSIS
result = BindSuperWatchers( class )
d0 a0
FUNCTION
This function is called internally during METH_INIT of all classes
and metas.
A search is done on the immediate superClass' attributes. Any
watchers found on the class' attribute list are copied to the
passed class' attribute.
Thus, if a new class subclassed off of WindowClass was created
while running browser, the watcher that was watching all of the
window classes will watch that new window class as well.
INPUTS
META class; - the (sub)class to bind the watchers.
OUTPUTS
BOOL result; - the result code.
FALSE indicates failure to copy all the watchers. Probably ran out
of memory allocating list nodes.
RESULT
The class' watched variables can now send out notification to the
old class watchers for any new objects that are created and stored
there, or for any changes in value made to the watched variable.
BUGS
none known.
NOTES
SEE ALSO
BindWatchers()
AddWatcherNode()
AddClassWatcher()
WatcherDispatch()
NAME
BindWatchers -- binds all object's attributes' watched wv_firstClass
to the appropriate spot in the object's class.
SYNOPSIS
BindWatchers( object )
a0
FUNCTION
This function is called internally during METH_INIT of all objects.
It sets all watched variables in the object to have their
wv_firstClass pointer pointing to the class' attributes' SList,
like it is supposed to.
This allows notification of any changes to the watched variable to
be sent out on a class basis -- any object of the class will
attempt to send notification to both the specific object, and
the associated class.
An example is in browser.c which is notified whenever any object
is added to the ATTR_GUICHILDREN of any object whose class is
a descendent of WindowClass.
INPUTS
OBJECT object; - the object to bind the watchers.
OUTPUTS
RESULT
The object's watched variables can now send out notification to the
class watchers.
BUGS
none known.
NOTES
SEE ALSO
BindSuperWatchers()
AddWatcherNode()
AddClassWatcher()
WatcherDispatch()
NAME
BlockMethod -- [un]blocks via a METH_FLAG_PREBLOCK, the method
in a given class.
SYNOPSIS
BlockMethod( class, name, pri, block )
a0 a1 d0 d1
FUNCTION
This function will search the class for a method of the given name.
If pri is non-zero, the patched verbs list of the class is searched
for a method patch of the given name and priority.
This handle is then either PRE_BLOCK'd or un-PRE_BLOCK'd,
according to the block flag.
INPUTS
META class; - the class where the method is found.
char *name; - the name of the method to [un]block.
WORD pri; - the priority (or nearest priority) of where
the block should take effect.
If pri is non-zero, a patch of that pri must
exist.
WORD block; - whether to block (TRUE) or to unblock (FALSE)
OUTPUTS
none
RESULT
A method may be [un]blocked.
BUGS
none known. Not yet tested! (07 Oct 1992)
NOTES
SEE ALSO
DSM() DoShadow()
InvalidateCache()
SetMethodArgs()
AddMethods()
DestroyMethodTable()
FindMethodHandle()
RemoveAllPatches()
SetupMethodTags()
NAME
ChangeWatchedValue -- Changes a watched variable's value.
SYNOPSIS
ChangeWatchedValue( wv, new )
a0 d0
FUNCTION
Changes the watched variable to the passed new value.
If any parties are interested, WatcherDispatch is called with
either W_CHANGE_ZERO or W_CHANGE_NON_ZEROin the flag parameter.
INPUTS
W_VALUE wv; - a watched variable to change.
long new; - the value to change to.
OUTPUTS
RESULT
The value is changed, and all parties notified.
BUGS
none known.
NOTES
SEE ALSO
WatcherDispatch()
NAME
CopyDefaultAttributes -- Copy the default attrs into the instance
SYNOPSIS
CopyDefaultAttributes( object )
a0
FUNCTION
This function will copy the default values, specified in the
object's class, into the object. It is executed by both MetaClass
and MetaCluster, and by both rootClass and rootCluster in the
METH_CREATE method.
It assumes the object is already filled with ZEROs.
INPUTS
OBJECT object; - The object whose attributes should be initialized.
OUTPUTS
none
RESULT
The object's attributes are initialized to the attribute default
values stored in the object's class.
Object is assumed to have already been initialized to ZEROs.
BUGS
none known.
NOTES
object is a required parameter.
SEE ALSO
PrepareAttrTags()
AddAttributes()
FreeAttributes()
FindAttribute()
FindAttrDefn()
NAME
CreateMeta -- Creates a self-referencing class description.
SYNOPSIS
meta = CreateMeta( description )
d0 a0
FUNCTION
This function creates a Meta.
A Meta is a class whose class is itself. Metas are useful for
describing Classes and such. The current system creates two
Metas: MetaClass and MetaCluster.
The description is used to create the Meta using the attributes
and superClass pointers. The superClass field, the attribute
table and the method table are all filled in. The name is NOT,
nor is any other information in the description touched.
The passed description's object and class pointers are set up as
the allocated meta, the method is initialized either to METH_INIT
(if the passed description's method as NULL) or left as passed
(if not NULL).
CreateMeta then returns "DSM(INVOKE_FIND_SELECTOR, description)".
This implies several things:
You can create meta structures that need initialization by
passing the appropriate arguments in the InitMeta structure.
See the InitMeta structure for more details.
Your METH_INIT methods should, then, -do-the-right-thing- when
passed its own meta, rather than a proper instance of
that meta. The correct method for checking for such an event
is to compare 'object' with 'object->cob_class' as in:
MyMethod(METHOD_ARGS, MYMETHODARGS)
{
if (object == object->cob_class)
{
/*
* we were passed a meta, so
* do what we needed to do with that.
*/
} else
{
/*
* We were passed a proper instance, so do
* what is necessary here.
*/
}
}
Specifically, you should NOT do a comparison between 'object'
and 'class'. Class can change if called as a superclass method.
The object might still be a meta, just not THAT method's meta....
As always, the following methods should also handle being sent a
Meta: METH_DESTROY, METH_REMOVE.
METH_SUB should also handle Metas by filling in the superClass
pointer and passing the arguments to CreateMeta.
The following code segment may be useful:
MethodMetaSub(METHOD_ARGS, name, superClass, attrList, verbList)
{
if (!superClass)
superClass = object;
if (object == object->cob_class)
{
struct InitMeta *im;
im = (struct InitMeta *)&object;
im->im_object = im->im_class = NULL;
im->im_method = NULL;
im->im_super = superClass;
return CreateMeta(im);
}
.
.
.
}
A consequence of using METH_SUB to create new Metas is that
the initialization parameters are truncated to match the
METH_SUB parameter description, which might not pass all the
required parameters into the InitMeta structure sent to
CreateMeta! Please remember what you are doing.
The description structure that is passed is a fixed length header
with a variable length number of additional arguments (which should
match the initialization routine CreateMeta calls: either the contents
of description->im_method OR METH_INIT if that is NULL). As a result,
this argument list MUST be terminated by a METHOD_END. Note that
all method invocations have a METHOD_END located one argument
passed their last defined argument, thus allowing the above code to
work properly.
Your initialization routine is responsible for setting the Meta's name
and adding the meta to ShadowBase->sb_metaTree. However, it should
specifically NOT setup the attribute tables and method tables (like
it would in the case of a new class) as CreateMeta has already
done that for you.
The instances of Metas have, likewise, the same attributes as the Meta
(as part of their instance, where the Metas have those attributes in
both the INSTANCE and in their attribute description table).
Reminder:
the METH_REMOVE of the meta must distinguish between the case
where the passed object != meta (meaning the object is an
instance of Meta, and so should be removed from the
ATTR_INSTANCETREE of the object->cob_class) and the case where
object == meta (meaning the object *is* the meta, and should be
removed from the system's metaTree -- &ShadowBase->sb_metaTree).
Similarly for METH_DESTROY -- don't drop the object's cob_class
when you destroy the meta ie: object == object->cob_class), and
do transfer the class:
if (object == class) IpcARGTransfer(msg, 1);
INPUTS
struct InitMeta *im; - the initialization description. See includes
OUTPUTS
META meta; - the meta that was created. NULL if error.
RESULT
BUGS
none known.
NOTES
SEE ALSO
UseObject()
DropObject()
FindInstanceOfMeta()
NAME
CreateObject -- creates an object with the same data as the ptr.
SYNOPSIS
object = CreateObject( ptr, size )
d0 a0 d0
FUNCTION
This function creates a ClasslessObject, which can be UseObject()'d
and DropObject()'d at will, whose included data is the data
located in ptr, covering "size" bytes.
If given both a non-NULL pointer and non-zero size, it allocates
an object of sizeof(struct ClasslessObject)+size and sets up
the fields according to what a ClasslessObject should look like:
clb_size = size;
clb_useCount = 1;
clb_class = NULL;
As noted, the returned object is Use'd once, so it should be
DropObject()'d when its life expires.
INPUTS
void *ptr; - the object to effect the change upon.
ULONG size; - the size of the data pointed to by ptr.
OUTPUTS
OBJECT object; - the allocated object with the (optional) passed
data. NULL if error.
RESULT
A new ClasslessObject is created.
BUGS
none known.
NOTES
SEE ALSO
UseObject()
DropObject()
NAME
DestroyMethodTable -- frees the array of methods.
SYNOPSIS
DestroyMethodTable( table )
a0
FUNCTION
This function will destroy the MethodTable's array of
MethodHandlers (usually the class' meta_verbs field).
It resource-tracks the procObject, defnObject, and method names
in the MethodHandler elements. At this point, the routine will
DropObject() or DropIPCPort() or DropString() these fields.
INPUTS
struct MethodTable *table; - required parameter. Usually found in
class->meta_verbs.
OUTPUTS
RESULT
The array, if a non-NULL ptr, is freed.
BUGS
none known.
NOTES
SEE ALSO
DSM() DoShadow()
InvalidateCache()
SetMethodArgs()
AddMethods()
FindMethodHandle()
BlockMethod()
RemoveAllPatches()
SetupMethodTags()
NAME
DropObject -- resource tracking for shadow objects.
SYNOPSIS
DropObject( object )
a0
FUNCTION
This function decrements the object's cob_useCount.
You should Drop() an object when you free a structure that had a
pointer-to-object in it. In addition, certain method calls, like
METH_INIT return an object to you. When you are done using the
pointer, you are expected to drop the pointer.
A word about self-referencing. Self-referncing is an evil problem
in useCount systems. You should DropObject() all self-references
during the METH_REMOVE call of an object. For instance, if your
class maintained a binary tree of gadget objects, and these
gadget objects pointed back to the window object, the
IDCMP_WINDOWCLOSE should do a METH_REMOVE on the window, which in
turn should METH_REMOVE it's gadgets, and those gadgets should
remove all references to the window object during that METH_REMOVE
call.
If the useCount of the object drops to zero furing DropObject(),
the object's destructor (METH_DESTROY) is called. If the object
in question has no class, than it is assumed to be a
ClasslessObject, and the clb_size is looked at. If this field
is non-zero, the object is freed, with
"FreeMem(object, object->clb_size);"
You must be careful when designing asynchronous METH_DESTROY
methods -- please see IpcItemTransfer() for further details.
INPUTS
OBJECT object; - the object to effect the change upon.
OUTPUTS
RESULT
BUGS
none known.
NOTES
SEE ALSO
UseObject()
IpcItemTransfer()
Introduction.doc :: resource tracking
NAME
DropString -- Removes a reference to a system string.
SYNOPSIS
DropString( buffer )
a2
FUNCTION
This function searches the system string list for the system
string corresponding to the passed buffer, then decrements
the internal usage counter for that system string by one.
If the counter becomes zero, that system string is freed from
memory.
If no string can be found to match buffer, no action is taken.
INPUTS
char *buffer; - equivalent string to the system string that you
want the system to drop a reference to.
OUTPUTS
RESULT
The system string corresponding to the passed buffer has one
fewer references to it.
BUGS
none known.
NOTES
The buffer should be word-aligned for faster access. long-word
aligned is preferred.
SEE ALSO
UseString()
QuickUseString()
FindString()
QuickDropString()
NAME
DSM -- parses out the requested method, calls and/or sends out
the appropriate function(s)/message(s)
SYNOPSIS
result = DSM(flags, arguments )
d0 d1 a1
FUNCTION
This function is the work horse of the entire system. It is
responsible for sending off all METHODs, whether synchronously,
asynchronously, or as a function call. In addition, it also sends
off all method patches as requested.
DSM() takes a number of flags which are found in <shadow/message.h>.
They are meant to override similar flags which are located in the
METHOD_TAG definition of each individual method. Following is their
meaning:
INVOKE_CALL - DEFAULT assumption -- calls method as function
unless specified otherwise in the METHOD_TAG
INVOKE_SYNC - Overrides the method's mtag_threadstat field.
The method is sent as a synchronous message
to the method's destination process [usually
mtag_procObject; see: SetupMethodTags and
INVOKE_WITH_PROCESS], unless the calling
process belongs to a superset (non-proper)
of the destination's process, in which case
the method is called as a function.
INVOKE_ASYNC - Overrides the method's mtag_threadstat field.
The method is sent as an asynchronous message
to the method's destination process [usually
mtag_procObject; see: SetupMethodTags and
INVOKE_WITH_PROCESS], unless the calling
process belongs to a superset (non-proper)
of the destination's process, in which case
the method is called as a function.
INVOKE_FORCE - Used in onjunction with above flags. See
next three flags.
INVOKE_FORCE_SYNC - Overrides the method's mtag_threadstat field.
The method is sent as a synchronous message
unless the calling process is exactly
equivalent to the destination process, in
which case the method is called as a funcion.
INVOKE_FORCE_ASYNC- Overrides the method's mtag_threadstat field.
The method is ALWAYS sent as an asynchronous
message. Irregardless of calling/destination
process.
INVOKE_FORCE_CALL - This is used to override the method's
mtag_threadstat and force a function call
equivalent.
INVOKE_WITH_PROCESS-This indicates that the passed argument array
has a preceding process object which should
be used as the destination process for the
method. The process will only be used
providing that it is required by the method
(ie: that the method is called synchronously
or asynchronously and meets the requirements
of the calling/destination process as
described in the INVOKE_[FORCE_][A]SYNC
flags above), AND if the
INVOKE_IGNORE_PROCESS flag is not set in the
mtag_threadstat field of the method. The
INVOKE_IGNORE_PROCESS is the exact equivalent
of the INVOKE_WITH_PROCESS. However, because
of the difference in both meaning and
placement, the INVOKE_WITH_PROCESS flag name
should be used with DSM(), and the
INVOKE_IGNORE_PROCESS should be used with
the mtag_threadstat.
INVOKE_FROM_SUPER - This flag indicates the wish to call a passed
class' superclass. The second field of the
arguments will be -modified- by DSM() to the
class' superclass, and the method then
invoked normally. Additional doMethod
function callback checking will occur -- both
for the original class and the superclass.
INVOKE_FIND_SELECTOR
- The selector is looked up in the system's
hashtable of strings using the FindString()
SHADOW library call. The address of this
system string is used to select the method
to call.
INVOKE_RETURN_MSG - The DSM() call returns a message which can be
used to later generate the actual method as
specified in the passed arguments. All
resource tracking on the arguments is done
within DSM(). The returned message can
be junk()'d with the JunkIPCMessage()
SHADOW library call, or the method can be
sent as an argument to another function,
and in that method you can call the
ParseShadowMessage() to call the method
associated with the message. Please see
the examples in ShadowLibFuncs.doc
under the PreParseShadow() .lib function.
If the "flags" argument specifies that the methods should be forced
to send all methods INVOKE_ASYNC or INVOKE_FORCE_ASYNC, then a single
message is sent to the primary handle's procObject asynchronously
with the function callback set back to DSM. When DSM() is then
called by the other proces (the message having been parsed out by
MessageParse(), usually handled by ParseShadowMessage()), the method
and all of its patches are sent out without the INVOKE_ASYNC
specification. This corrects the case where a patch is supposed
to be able to -synchronously- control any subsequent patches
(METH_FLAG_CHECK_CONTINUE). Obviously if all methods and all
patches were sent out asynchronously, there would be no chance
for a synchronous-type behaviour to act correctly. Therefore,
the initial send is asynchronous to the caller, but the complete
method handling, including synchronous calling of patches,
occurs synchronously to the called process.
Consequently, if the method itself (as represented in its METHOD_TAG
description) is flagged with INVOKE_FORCE_ASYNC, and DSM() is called
with the INVOKE_ASYNC flag, then there are actually -two- messages
that are sent. One is the message described above which handles the
synchronous patch-handling asynchronously to the calling process,
the other message occurs when the method is processed in the called
task -- the method was created as being invoked asynchronously,
independently from where it is called, so another message is sent
back to the same process!
Representing the method as INVOKE_ASYNC, as opposed to
INVOKE_FORCE_ASYNC, will avoid this problem, although in this case
you may not be able to make the process asynchronous enough to
avoid the cases where synchronous behaviour is unwanted.
The best way to avoid these problems is to use the
INVOKE_FORCE_ASYNC flag in METHOD_TAGs as little as possible, and
only call DSM() with the asynchronous flag as needed. The .lib
functions DoShadowAsync(), DoShadowInProcessAsync(), etc. all
call DSM() with the INVOKE_ASYNC bit set.
If you cannot avoid these issues, you may want to consider creating
your own process class for the method, allowing, therefore, an
INVOKE_ASYNC bit to correctly be asynchronous to every process
-except- when called from within this "double-nested" DSM().
In that case, because the calling process and the method-destination
process are equivalent, the method is invoked via the function,
and not another message. There is more overhead in creating your
own process class (an extra CreateSubClass() call), but it may be
worth your trouble....
In addition to these passed flags, many of the mtag_flags located in
the method description are used to enhance DSM()'s capabilities of
sending methods across process boundaries. These flags can be found
in <shadow/misc.h>:
METH_FLAG_OBJECT - The mtag_procObject is interpreted as the
destination process.
METH_FLAG_PORT - The mtag_procObject is interpreted as an
IPCPort to which method-messages are sent.
METH_FLAG_CLASS - The mtag_procObject is interprted as a
class of process objects. This class is
instantiated, and the resulting process
object is used as the destination for
that particular invocation.
METH_FLAG_OBJECT_AS_DEST
- The object inside of the passed arguments
(ie: *(OBJECT *)arguments) is considered the
destination for the method. This is
particularly useful for process methods which
must (for reasons of port allocation or other
Signal-bit allocation, etc.) be run in the
process with which the process-object
corresponds.
METH_FLAG_SPEC - The mtag_procObject is interpreted as a
pointer to a struct MethInvokeSpec
[see: <shadow/method.h>], the complete
meaning of which depends on the above four
flags in the following manner:
METH_FLAG_SPEC | METH_FLAG_OBJECT
mis_instanceName is the name of the process object to use
as the destination object.
mis_className is the class name of the class of the
above process object.
mis_metaName is the meta's name of the meta of the
above class. Usually this is
META_CLASS.
METH_FLAG_SPEC | METH_FLAG_PORT
mis_instanceName is the name of the IPCPort to use as the
destination port. This port will NOT
be created, but must exist when the
method is called.
mis_className is NULL
mis_metaName is NULL
METH_FLAG_SPEC | METH_FLAG_CLASS
mis_instanceName is NULL
mis_className is the class name of the process to
create.
mis_metName is the meta's name of the meta of the
above class. Usually this is META_CLASS.
METH_FLAG_SPEC | METH_FLAG_OBJECT_AS_DEST
the METH_FLAG_SPEC is meaningless in this case as the
METH_FLAG_OBJECT_AS_DEST never uses the mtag_procObject
field.
When the process/port is looked-up/created,
the process/port may replace the
MethInvokeSpec structure, eliminating the
need to lookup the object/class/port again.
To do this, set the SPEC_SAVE_BINDING flag
in the mis_flags field of the MethInvokeSpec
structure.
The following METH_FLAGs are passed in at method or patch creation
in the MethodTag mtag_flags field:
METH_FLAG_[POST|PRE]_BLOCK
- ends the sending of methods off as DSM()
works from the highest priority patch, to
the normal MethodHandle, to the lowest
priority patch. POST_BLOCK ends the
method chain after -that- method in the
patch-chain is sent off, PRE_BLOCK ends it
BEFORE that method is sent off.
METH_FLAG_NO_RTRN
- informs DSM() that a patch or method has no
return value. By default, all methods and
patches have return values.
Note that this is a change from SHADOW 4!
METH_FLAG_CHECK_CONTINUE
- checks the return value returned in d1
(that's d1, not d0). If d1 is TRUE, then
the method-chain is continued, if FALSE
(zero), then the method chain ends at that
point.
A method-chain exists whenever a method is patched. These patches
are called from high priority to zero, when the regular handle is
called, and then lower priority patches are called. This chain
of method calls can be terminated by the *_BLOCK or CHECK_CONTINUE
flags mentioned above. Patches are discussed in more detail in both
the ShadowLibraryMethods.doc and the Introduction.doc.
Thus, we have a picture of DSM(). First, the doMethod() callback of
the passed class is checked to see if someone else wants to process
the method calls (see NOTE: below). Then , if necessary,
the superclass is loaded and the same doMethod() check is made.
The selector is rendered into a legal system selector, and the
method found in the class or class hierarchy. The method is then
checked to see if it's merely a function call, or a series of
function/[a]synchronous calls in a patch-chain. If the former,
the method is invoked, if the latter, a series of actions are taken
to invoke the method correctly, whether as a function call (as an
INVOKE_[A]SYNC might turn out to be), or as a message of some kind,
or as a series of function calls and message sends.
To avoid headaches, just use the Do*Shadow*() calls in the .lib
instead....
INPUTS
void **arguments; - a pointer to the arguments. First should be the
object, then a valid class, then a method, then
the rest of the arguments according to the
ArgumentTag structure, ending with a METHOD_END
(0x80000001)
ULONG flags; - if low byte non-zero, treat as a specification
for the type of method to send (INVOKE_CALL,
etc.). A INVOKE_FORCE alone specifies
that the method should be called. The flag
affects any method patches as well.
INVOKE_SUPER indicates the method should be
sent to the superclass of the class as poassed
in arguments[1].
INVOKE_FIND_METHOD indicates that the method
needs to be lookup up in the systemString via
the FindString call.
OUTPUTS
void *result; - result from method parse.
RESULT
BUGS
none known.
NOTES
DSM() caches methods for faster lookups (a bit less than thrice as
fast in worst case function calls).
DSM() checks the class' doMethod function callback both BEFORE and
AFTER any INVOKE_SUPER handling. This callback should act like
DSM(), if you want to change the way DSM() works. The callback
does, however, take its parameters in d0/a0 not d1/a1. The callback
is located in the class structure -- inside of the struct CoreClass,
to be exact [<shadow/coreMeta.h>]. As DSM() searches up the class
hierarchy for the method, each class' doMethod() callback is
checked. if it exists, the function is then called.
Use the Do*Shadow*() method calls instead!
SEE ALSO
Do*Shadow*()
InvalidateCache()
SetMethodArgs()
AddMethods()
DestroyMethodTable()
FindMethodHandle()
BlockMethod()
RemoveAllPatches()
SetupMethodTags()
NAME
FindAttrDefn -- Finds the attribute structure in the class
SYNOPSIS
attribute = FindAttrDefn( class, name )
d0 a0 a1
FUNCTION
This function finds the Attribute structure (the element in the
class' array) of the specified class.
If the class has a callback attribute function, that function is
called instead.
Otherwise, the array is radix searched for the attribute whose
name corresponds to FindString(name).
INPUTS
META class; - the class whose attribute is wanted
returns NULL for a NULL class.
char *name; - the name of the attribute to find.
OUTPUTS
struct Attribute *attribute; - pointer to the Attribute structure as
specified in the class.
RESULT
BUGS
none known.
NOTES
The attribute callback function is called:
ccl_attrDefnFunc() and is located in the struct CoreClass
described in <shadow/coreMeta.h>.
SEE ALSO
PrepareAttrTags() FindString()
AddAttributes()
CopyDefaultAttributes()
FreeAttributes()
FindAttribute()
NAME
FindAttribute -- Finds the instance of the attribute in the object
SYNOPSIS
attribute = FindAttribute( object, name )
d0 a0 a1
FUNCTION
This function will find the specified structure inside of the object
and return the address of that structure.
Calls FindAttrDefn() on the object's class.
INPUTS
OBJECT object; - the object whose attribute is wanted.
returns NULL for a NULL object, or
an object with a NULL class.
char *name; - the name of the attribute to find.
OUTPUTS
void *attribute; - pointer to the object's attribute. This
pointer points to the insides of an object.
RESULT
BUGS
none known.
NOTES
Calls FindAttrDefn internally.
SEE ALSO
PrepareAttrTags()
AddAttributes()
CopyDefaultAttributes()
FreeAttributes()
FindAttrDefn()
NAME
FindInstanceOfMeta -- Bi-level search for instances of a Meta (Classes!)
SYNOPSIS
class = FindInstanceOfMeta( className, metaName )
d0 a0 a1
FUNCTION
This function is useful for finding a Class. A Class always resides
in the ATTR_INSTANCETREE of its defining Meta (until removed via the
METH_REMOVE method). The Metas all reside in ShadowBase->sb_metaTree.
Therefore, it takes two FindWatchedTreeStringNode() calls to find a
class (or Cluster).
This is how FindShadowClass() and FindShadowCluster() are #defined....
INPUTS
char *className; - the name of the class you are looking for.
char *metaName; - the name of the Meta that the class is in.
OUTPUTS
OBJECT class; - the pointer to the class. NULL if can't find.
RESULT
BUGS
none known.
NOTES
You should DropObject() the class when you are finished using it.
SEE ALSO
UseObject()
DropObject()
CreateMeta()
FindNamedObject()
NAME
FindMethodHandle -- finds the associated handle in the class.
SYNOPSIS
handle = FindMethodHandle( class, method )
d0 a0 a1
FUNCTION
This function will search the class' verb table for the
required method. It does not look in any superclasses to
find it.
INPUTS
META class; - the (optional) class in which to find the method.
char *method; - the name of the method to look for. MUST be the
system string equivalent (you can get this from
the FindString() function.
OUTPUTS
struct MethodHandle *handle; - the returned handle. NULL if not
found.
RESULT
BUGS
none known.
NOTES
SEE ALSO
DSM() DoShadow()
InvalidateCache()
SetMethodArgs()
AddMethods()
DestroyMethodTable()
BlockMethod()
RemoveAllPatches()
SetupMethodTags()
NAME
FindNamedObject -- Tri-level search for instances of a Class of a Meta
SYNOPSIS
object = FindNamedObject( instanceName, className, metaName )
d0 d0 a0 a1
FUNCTION
This function is useful for finding a named OBJECT like a process.
A Process' Class always resides in the ATTR_INSTANCETREE of its
defining Meta (until removed via the METH_REMOVE method). Likewise,
the process OBJECT always resides in the ATTR_INSTANCETREE of its
defining process class. Therefore, it takes three
FindWatchedTreeStrngNode() calls to find a named object.
INPUTS
char *instanceName; - the name of the object we're looking for.
char *className ; - the name of the class you are looking for.
char *metaName ; - the name of the Meta that the class is in.
OUTPUTS
OBJECT object ; - the pointer to the object. NULL if can't find.
RESULT
BUGS
none known.
NOTES
You should DropObject() this object when you are finished using it.
SEE ALSO
UseObject()
DropObject()
CreateMeta()
FindInstanceOfMeta()
NAME
FindNodePriInSList -- Finds an object in the singly linked list
SYNOPSIS
object = FindNodePriInSList( list, pri, name )
d0 a0 d0 a1
FUNCTION
This function finds an object in a singly linked list with the
given name at the given priority (list is ordered by
priority).
INPUTS
SList *list; - a pointer to the list in which to find
the object.
long pri; - the priority
char *name; - the name it was added as.
OUTPUTS
OBJECT object; - the object, if found. NULL otherwise.
RESULT
BUGS
none known.
NOTES
The found object is UseObject()'d, please DropObject() it when you
are finished using the pointer.
SEE ALSO
AddSListNode() AddWatchedSListNode()
RemoveSListNode() RemoveWatchedSListNode()
UseObject()
DropObject()
NAME
FindString -- Find a system string
SYNOPSIS
string = FindString( buffer )
d0 a2
FUNCTION
This function hashes the buffer string and searches on the
collision binary tree for any matches.
It will return the system string, if it finds it. It will NOT
increment the internal useCount, so you should not use what is
returned as either a system string, nor even as a string, but
merely as an address you are searching a table for -- and
even then, you must be careful of race conditions, the address
should remain valid for the entire time you are searching a
table or structure, or the table/structure must be locked in
memory during the time you look up the string and the time
you are searching the table.
INPUTS
char *buffer; - the buffer whose system string you want to find.
Given a NULL, will
return a NULL
OUTPUTS
char *string; - the string, if found. NULL if no string.
RESULT
BUGS
none known.
NOTES
The buffer should be word-aligned for fast access and long-word
aligned for fastest access.
SEE ALSO
UseString()
QuickUseString()
DropString()
QuickDropString();
NAME
FindTreeNode -- Finds the object in the binary tree
SYNOPSIS
object = FindTreeNode( bt, key )
d0 a0 d0
FUNCTION
This function returns the first object in the binary tree that matched
the key passed to the function.
Note that a corollary function FindTreeStringNode() is usually defined
as FindTreeNode(bt, FindString(name)).
The object is Used() via the UseObject() call. When the pointer that
is returned is no longer needed, it should be Drop()'d via the
DropObject() call.
INPUTS
AVLTREE *bt; - a pointer to the root of the binary tree.
ULONG key; - the key to look for.
OUTPUTS
OBJECT object; - the object that is found
NULL is returned if no object is found.
RESULT
The node is located in the binary tree.
BUGS
none known.
NOTES
Please DropObject() any objects returned when no longer needed.
Remember that the keys are sorted unsigned, not signed.
SEE ALSO
UseObject()/DropObject()
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FreeTreeAllNodes() RemoveWatchedTreeNode()
RecurseTree() RemoveWatchedTreeStringNode()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
FreeTreeAllNodes -- Frees all nodes in a particular binary tree
SYNOPSIS
FreeTreeAllNodes( bt )
a0
FUNCTION
This function will remove all nodes off of the binary tree, dropping
all objects, and all strings.
The binary tree is assumed to contain objects sorted on a string as
a key. Please do not call it on any other type of binary tree, as
it would be dropping potentially non-existant string objects.
V4.2 UPDATE! You may now call it with a binary tree that is sorted
on keys identical to the pointer to the objects each node holds.
ie: keys added with:
AddTreeNode(&bt, object, object);
-or- with keys of less than 256, which are assumed to be merely
longwords and not pointers to strings....
INPUTS
AVLTREE *bt; - a pointer to the root of the binary tree.
OUTPUTS
RESULT
bt is now a pointer to an empty binary tree.
BUGS
none known.
NOTES
Don't call this function on a binary tree sorted by keys that aren't
system strings, aren't less than 256 and aren't equal to the
corresponding object.
SEE ALSO
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode() RemoveWatchedTreeNode()
RecurseTree() RemoveWatchedTreeStringNode()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
FreeAttributes -- Frees all Attribute structures for the class
SYNOPSIS
FreeAttributes( table )
a0
FUNCTION
This function will free the array of Attributes in the
AttributeTable. Called during METH_DESTROY for classes and metas.
INPUTS
struct AttributeTable *table; - pointer to the attribute table to
free. Probably a pointer into a
class that is going away.
OUTPUTS
none
RESULT
The memory allocated in that table is freed. The Table structure
itself is NOT freed.
BUGS
Should probably be called DestroyAttributeTable()
NOTES
table is a required parameter
This is a system function, and probably not something that you will
need to call.
SEE ALSO
PrepareAttrTags()
AddAttributes()
CopyDefaultAttributes()
FindAttribute()
FindAttrDefn()
NAME
FreeClassWatchers -- frees all the watchers in the class' attributes
SYNOPSIS
FreeClassWatchers( class )
a0
FUNCTION
This function frees all watchers left on any of the class'
attribute-watching SLists.
INPUTS
META class; - the class whose attributes' watchers need to be
removed.
OUTPUTS
RESULT
All watchers in a class are removed.
BUGS
none known.
NOTES
For some reason, class watchers need to be removed from the class
when the class is removed.
Therefore, the METH_REMOVE for metas and roots calls this function.
SEE ALSO
FreeObjectWatchers()
AddClassWatcher()
NAME
FreeItem -- Frees an element belonging to a MemoryList
SYNOPSIS
FreeItem( list, ptr )
a0 a1
FUNCTION
This function frees an element that was allocated via the
AllocateItem() function. The element may, or may not, be returned
to Exec's free memory pool, but may, thereafter, be re-used by
AllocateItem() for some other program.
INPUTS
SEMLIST list; - the MemoryList the element belongs to.
void *ptr; - the element pointer
OUTPUTS
RESULT
The element is returned to be re-used by AllocateItem for the
specified MemoryList.
BUGS
Infinite loop occurs if ptr was not on the MemoryList to begin with.
NOTES
The MemoryList passed MUST be the MemoryList from which the element
was allocated.
SEE ALSO
InitTable()
AllocateItem()
FreeTable()
NAME
FreeObjectWatchers -- frees all the watchers in the object's vars.
SYNOPSIS
FreeObjectWatchers( object )
a0
FUNCTION
This function removes all watchers from all variables in the object.
INPUTS
OBJECT object; - the object whose watched variables need to be
removed.
OUTPUTS
RESULT
All watchers of all watched variables in the object are removed.
BUGS
none known.
NOTES
This function, as opposed to FreeClassWatchers(), can be called in
the METH_DESTROY. The Metas and Roots currently call this function.
SEE ALSO
FreeClassWatchers()
AddClassWatcher()
NAME
FreeTable -- free all the memory nodes on the MemoryList
SYNOPSIS
FreeTable( list )
a0
FUNCTION
This function frees all resources that the MemoryList acquired
during run-time. This means that any outstanding MemoryNodes are
thereafter freed -- and therefore not usable to whomever may own
them. No attempt is made to ensure all items have been released
before all outstanding MemoryNodes are freed by the freefunc()
originally passed to InitTable.
FreeItem automatically frees MemoryNodes when it "feels" there are
plenty of free elements available for use. However, that means
that even when all elements are FreeItem()'d, there will still be
many MemoryNodes on the MemoryList. This function will free those
remaining MemoryNodes.
INPUTS
SEMLIST *list; - the MemoryList to purge.
OUTPUTS
RESULT
The MemoryList no longer contains any outstanding resources.
BUGS
none known.
NOTES
The notion of '"feels" there are plenty of free elements' is
intentionally vague.
SEE ALSO
InitTable()
AllocateItem()
FreeItem()
NAME
GetObject -- Semaphored access to an object in a public area.
SYNOPSIS
object = GetObject(objectPtr )
d0 a1
FUNCTION
In some attributes, there may be object pointers that you need
to retrieve from that attribute. On the other hand, somebody else
might change it at the same time.
This function uses the ShadowBase->sb_semSemaphore to protect the
access to the objectPtr. The object that is returned is returned
Use()'d, so when you are done with the object you should call
DropObject(object) on it.
INPUTS
OBJECT *objectPtr; - the pointer to the structure element that
holds the object pointer you want.
OUTPUTS
void *object; - the object that *objectPtr points to.
RESULT
object returned is UseObject()d once.
BUGS
none known.
NOTES
SEE ALSO
RemoveObject()
SetObject()
NAME
GetShadowError -- Get an error code from SHADOW
SYNOPSIS
result = GetShadowError()
d0/d1
FUNCTION
This function retrieves the last SHADOW error and suberror that
occurred within the calling process' context.
This is useful to use when you need to differentiate between
a failure to send a message, and an asynchronous send which ALWAYS
returns a NULL, or a successful, but NULL-returning, method.
You should ClearShadowError() first, of course....
/*
* The following is included for clarity, but is actually
* present in the shadow_proto.h include file.
*/
#define ClearShadowError() SetShadowError(0,0);
.
.
.
union {
double tempD;
ULONG tempV[2];
} retval;
ClearShadowError()
if (!DoShadow(object, NULL, DO_SOMETHING, METHOD_END))
{
retval = GetShadowError();
/*
* tempV[0] is the error code.
* tempV[1] is reserved at the moment, and is garbage for now.
*/
switch(errorCode = retval.tempV[0])
{
/*
* The following flags are from misc.h
*/
case 0:
/*
* No Error!
*/
case NO_SHADOW_PROCESS:
/*
* Could not retrieve an error because the current
* process is not registered with SHADOW.
*/
case CANNOT_ALLOCATE_OBJECT:
/*
* SHADOW could not allocate a new object.
*/
case CANNOT_ALLOCATE_PROCESS:
/*
* The method was supposed to invoke a process to
* handle it, but failed to create the process.
*/
case CANNOT_SEND_MESSAGE:
/*
* Either:
* a) port is blocked.
* b) no process to send to/from.
* c) message could not be allocated.
*/
case CANNOT_FIND_METHOD:
/*
* Could not find a method to send to!
*/
default:
}
}
}
INPUTS
<none>
OUTPUTS
double result; - low 32bits (d0) are the error, High
32bits (d1) are the error subcode.
Be careful if your compiler starts
checking for a double return in the
68881 processor, instead of d0/d1!!!
RESULT
BUGS
none known.
NOTES
SEE ALSO
SetShadowError
NAME
GetTagsSize -- gets the size of a NULL terminated aray.
SYNOPSIS
size = GetTagsSize( tags, size )
d0 a0 d0
FUNCTION
This function will find the size of a longword-NULL-terminated
array. The NULL termination should be valid for the first longword
of the last array element.
The passed size should be the size of each array element.
INPUTS
void *tags; - a pointer to the array. If NULL, returns NULL
long size; - the size of each element in the array.
OUTPUTS
long size; - the size of the array, including the NULL element.
RESULT
BUGS
none known.
NOTES
SEE ALSO
NAME
InitOOProgram -- initialize an AmigaDOS process as a shadow process
SYNOPSIS
result = InitOOProgram( name )
d0 a0
FUNCTION
This function will initialize the calling amigaDos process as
a SHADOW process. This means that tc_UserData is HANDS OFF from
that point on ('cept for read only). The process object is stored
in tc_UserData and all message ports, etc. are allocated.
This function MUST be called before initiating any non-CALL methods.
Any methods that would require a SYNC or an ASYNC message
require that a process object exist in tc_UserData of the calling
task.
If you want to use something other than PROCESS_CLASS, then you may
first set FindTask(NULL)->tc_UserData to NULL, then call METH_SUB
on the process class, then send that class a METH_CREATE, then
send the object that that returns a METH_ASSOCIATE. That's all
this function does.... [Excepting the METH_SUB call, of
course....] Please be sure NOT to use the object that is returned
(that is, do NOT DropObject() the returned process object!!!!)
There is an example of this sans the mETH_SUB call in
ShadowLibraryMethods.doc under the METH_PROC_ASSOCIATE method
description.
INPUTS
char *name; - the name to give the process object.
The name defaults to FindTask(NULL)->tc_Node.ln_Name when passed in
as NULL.
OUTPUTS
BOOL result; - result code
The result code is a boolean describing success or failure of process
object creation.
FALSE (0) is an error.
RESULT
Process object is created for the calling task.
BUGS
none known.
NOTES
tc_UserData is trashed (used)
SEE ALSO
RemoveCurrentProgram()
NAME
InitTable -- Initializes a memory table.
SYNOPSIS
result = InitTable( list, allocfunc, freefunc, size )
d0 a0 a1 d0 d1
FUNCTION
Shadow requires a number of very small elements to be coninually
allocated and freed. This function initializes a struct MemoryList
which attempts to ease the strain on AllocMem and FreeMem by
allocating and freeing blocks that are 32 times "size".
The individual elements are allocated via the AllocateItem() and
FreeItem() functions.
InitTable initializes the various parts of the passed MemoryList
structure.
INPUTS
SEMLIST list; - a MemoryList to initialize.
TABLENODE allocfunc(SEMLIST); - an allocation function that, given a
d0 a0 MemoryList, returns a MemoryNode
structure as a header to 32
elements to be doled out by
AllocateItem(). If passed as NULL,
the system uses an internal routine.
void freefunc(SEMLIST, TABLENODE);
a0 a1 - a free function that, given a
MemoryList and a MemoryNode, frees
the Node plus the 32 elements from
the List. If passed as NULL, the
system uses an internal routine.
long size - the size of each element.
OUTPUTS
BOOL result; - result code
The result code is a boolean indicating the success or failure of
the function call. A zero value indicates that an error occured.
RESULT
The specified list is initilized, the first 32 elements are
allocated, the semaphore is initialized, the memlst_semUse flag in
the structure is set to TRUE, and the memlst_size set to the
passed size.
BUGS
none known.
NOTES
It's not very flexible, but it's used for BinNodes, semaphores,
list, and MethInvokeSpec internal structures. It's got pretty good,
but not fantastic, performance. See "PerfTest MEMORY" results.
SEE ALSO
AllocateItem()
FreeItem()
FreeTable()
NAME
InitThread -- initializes the process object associated with the task.
SYNOPSIS
task = InitThread( task )
d0 a0
FUNCTION
This function is no longer valid under SHADOW V. If you have been
calling it and need directions on how to update your software,
please see both the ShadowLibraryMethods.doc and the
Introduction.doc about the PROCESS_CLASS.
NOTES
SUPERCEDED!
NAME
InsertSuperClass -- Take known class and insert another superclass level
SYNOPSIS
InsertSuperClass( subClass, newSuperClass )
a0 a1
FUNCTION
This function is useful for adding methods to a Class. Unfortunately,
it is currently impossible to remove these same methods once added,
so be very careful with what you're doing here!
Basically, this function takes the old superclass and makes the
newSuperClass the old subclass' superclass. This function also
flushes the entire method cache as it assumes that some method
cache lines might be incorrect.
INPUTS
META subClass; - the subclass whose superclass will be changed.
If NULL, no harm will come.
META newSuperClass; - the new superClass for the passed subClass
if NULL, the old superClass will remain.
OUTPUTS
<none>
RESULT
BUGS
none known.
NOTES
The newSuperClass is "swallowed" by this function. if you want to
keep the newSuperClass pointer valid within your sequence of
execution after this call, you will need to do something like:
InsertSuperClass(old, UseObject(new));
This function is only valid if the new superclass is, itself, a
subclass of the old subclass' superclass. IE:
Class A
|
/\
/ \
Class B Class C
\
\
Class D
It is valid to make Class B's new superclass either Class C or
Class D. However, Class D cannot have its superclass reset to
class B.
No class may be its own superclass! Such a class would never go away!
You may NOT add any new attributes with this call. That is, the
newSuperClass must not have any new attributes not located in the
oldSubClass. In addition, if you define default values for the
existing attributes, these default attributes will NOT propagate
down to the oldSubClass. This function is meant to add METHODS
ONLY! Do not attempt to use it for anything else or you will be
burnt.
SEE ALSO
UseObject()
DropObject()
CreateMeta()
NAME
InvalidateCache -- invalidates cache entries
SYNOPSIS
InvalidateCache( class, selector )
a0
FUNCTION
This function will invalidate all entries in the method's cache that
refer to the passed class and/or the passed selector.
If passed a NULL class, then every entry in the cache that contains a
selector field that matches the address of the passed selector is
cleared. You should call this whenever you create a selector on the
stack, or in memory, and then free the associated memory.
If passed a NULL selector, then every entry in the cache that
contains a class field that matches the address of passed class is
cleared. You should call this whenever a class is free'd.
if both fields are NULL, then the entire cache is flushed. This is
called whenever a program exits from memory. That's because there
are many methods which become invalid at that point, but
invalidating all of them would be tedious, so the entire cache is
flushed. Notice that that's with every PROGRAM, NOT every PROCESS.
If both fields are passed in as non-NULL, then cache entries are
only freed for those entries that match both the class and the
selector. However, I haven't found a good use for this case.
Perhaps you folks can?
INPUTS
META *class; - a class.
char *selector; - a method selector
OUTPUTS
RESULT
No more references to a defunct class exists in the method calling
cache. No more references to the defunct selectors exists in the
method calling cache.
BUGS
none known.
NOTES
SEE ALSO
DSM() DoShadow()
SetMethodArgs()
AddMethods()
DestroyMethodTable()
FindMethodHandle()
BlockMethod()
RemoveAllPatches()
SetupMethodTags()
NAME
IpcItemTransfer -- Transfers a resource from message to server.
SYNOPSIS
IpcItemTransfer( msg, num )
a0 d0
FUNCTION
This function will transfer the resource found in the num'th
item in msg to the calling server.
Basically, the IPC_ITEM_TRANSFER flag is cleared, and the
IPC_SERVER_OWNED flag is set.
This is very important to do when inside of a METH_DESTROY
method. You need to transfer the passed object out of the message!
INPUTS
struct IPCMessage *msg; - the (possibly NULL) message to xfer
resources from. If msg is NULL, no
action is taken.
long num; - the item number where the resource is
currently located.
OUTPUTS
none
RESULT
resource is no longer valid in the message.
BUGS
none known.
NOTES
SEE ALSO
IpcARGTransfer() macro
ppipc.library documentation. Not included in SHADOW, but available
on a Fred Fish disk.
NAME
JunkIPCMessage -- Frees a message allocated by MessageMaker
SYNOPSIS
JunkIPCMessage( msg )
a0
FUNCTION
This function will delete an IPCMessage, releasing all resources
which have not been IpcItemTransfer()'d.
The message itself is also deleted.
Message should have been allocated by MessageMaker, although that is
not the only legal case, it is the safest route to compatibility.
The PreParseShadow() function calls the MessageMaker() internally.
INPUTS
struct IPCMessage *msg; - the message to delete. If NULL, no action
is taken.
OUTPUTS
none
RESULT
One more message is gone.
BUGS
none known.
NOTES
SEE ALSO
MessageMaker()
IpcItemTransfer()
NAME
MessageMaker -- Creates a Message for the given MethodHandle & args.
SYNOPSIS
msg = MessageMaker( handle, args )
d0 a0 a1
FUNCTION
This function will create a ppipc message that MessageParse()
and ParseShadowMessage() can unroll in order to call a method
asynchronously across tasks.
Full resource tracking is done, and all resources are freed
during the JunkIPCMessage() call, unless an IpcItemTransfer()
was performed for that resource's item.
IpcItemTransfer should be done during METH_DESTROY.
INPUTS
struct MethodHandle *handle; - the method that the message should
serve. Set the low bit of the
address if this is actually a ptr
into a MethodHandle object as
returned from PatcherClass INIT.
void **args; - the arguments that should be placed,
one by one, into the message
structure. Full resource
tracking will be done for these
arguments according to the
ArgumentTag structure, so the message
can be sent asynchronously.
OUTPUTS
struct IPCMessage *msg; - The returned message.
RESULT
A new message is constructed.
BUGS
none known.
NOTES
SEE ALSO
JunkIPCMessage()
DropObject()
SetMethodArgs()
ParseShadowMessage()
MessageParse()
NAME
MessageParse -- Parses a message onto the stack.
SYNOPSIS
value = MessageParse( msg )
d0 a0
FUNCTION
This function will parse a message onto the stack according to the
ArgumentTag structure as passed inside of the message. The
message must have exactly the right number of items, or bad
things may happen.
The Method is then called, and its return value returned in d0.
There is also some magic which allows DSM() to be called as the
function, so that methods which are forced ASYNC by the flags
in an original DSM() call, actually work properly....
INPUTS
struct IPCMessage *msg; - should be a valid message set up by
MessageMaker().
OUTPUTS
void *value; - the return value of the method call.
RESULT
The METHOD is called.
BUGS
none known.
NOTES
SEE ALSO
MethodFuncParse()
DSM()
MessageMaker()
NAME
MethodFuncParse -- Copies the stack arguments back to the stack.
SYNOPSIS
return = MethodFuncParse( object, class, args, handle, flags )
d0/d1 d0 d1 a1 a2 d7
FUNCTION
This function will copy the arguments found in args onto the stack,
according to the ArgumentTag structure found in handle.
Unlike MessageParse(), it must deal with missing arguments -- ie:
it may encounter METHOD_END (0x80000001) before the end of the
ArgumentTag argument array. The missing arguments are NULL'd out,
then it calls the method function, and returns d0/d1 as a double.
D0 is what should normally be considered as the return value.
DSM() is incapable of returning real doubles at the current time.
D1 is used by DSM() for its METH_FLAG_CHECK_CONTINUE.
ParseShadowMessage() has some magic for storing D1 away for
synchronous method calls.
The 'msg' parameter of all Methods is NULL'd by MethodFuncParse().
INPUTS
OBJECT object; - the object being called.
META *class; - the class the method is defined in.
void **args; - the (other) arguments to the
function.
struct MethodHandler *handle;- the method's handle
ULONG flags; - set this field to zero for now. This
field reserved by system for future
expansion and current asynchronous
magic.
OUTPUTS
double return; - the return value is usually considered D0, but D1
is used by DSM() for its _CONTINUE checking.
RESULT
The METHOD was called.
BUGS
none known.
NOTES
SEE ALSO
MessageParse()
DSM()
ParseShadowMessage()
NAME
ParseShadowMessage -- parses the three types of SHADOW messages
SYNOPSIS
return = ParseShadowMessage( msg, flags )
d0 a0 d0
FUNCTION
This function parses the three types of messages that SHADOW
programs can receive -- AMET, SMET and JAZZ.
AMET message are asynchronous messages, and these message are
correctly handled by MessageParse(). The message is Junk()'d via
the JunkIPCMessage call.
SMET messages are synchronous message and these message are
correctly handled by MethodFuncParse(). The message is
replied to when MethodFuncParse() is finished.
JAZZ messages are message you can send. The function pointer should
be in the first element of the message, and the single argument to
the function should be in the second argument. No value is
currently returned -- but if someone needs to, please let me know.
They are currently unused. The message is returned when the
function is finished.
The flags override certain features of this function. There
are currently three flags:
SHADOW_RETURN_MSG_ALWAYS
SHADOW_RETURN_MSG_NEVER
SHADOW_RETURN_MSG_ON_FAILURE
By default (SHADOW_MSG_RETURN_NEVER), messages are always swallowed
by this function. If you wish the message to neither be replied to
or Junk()d via the JunkIPCMessage() call, call the function with the
SHADOW_RETURN_MSG_ALWAYS. The msg will then be returned to you for
whatver further processing you wish....
If you don't know whether this is a SHADOW message or not, you can
call the function with the SHADOW_RETURN_MSG_ON_FAILURE. If the
message is not an AMET, SMET or JAZZ message, the msg will be
returned to you for further processing. Note, however, that the
assumption is that the message -is- a struct IPCMessage, and not
some other form of message (like struct IntuiMessage, for instance).
You have been warned.
For the default behaviour, pass in the SHADOW_RETURN_MSG_NEVER
flag. This was the old behaviour of ParseJazzMessage() under SHADOW
4.
INPUTS
struct IPCMessage *msg; - a message sent to a SHADOW task's port.
ULONG flags; - one of three flags.
OUTPUTS
struct IPCMessage *return; - exact return is dependent on the flags
passed into ParseShadowMessage().
RESULT
The correct function is called.
BUGS
Does not handle unknown messages without replyports properly under
the SHADOW_RETURN_MSG_NEVER mode.
So don't send them!
NOTES
SEE ALSO
MessageParse()
MethodFuncParse()
NAME
PrepareAttrTags -- Prepares Attribute tags for class definition
SYNOPSIS
num = PrepareAttrTags( tags, countptr, super )
d0 a0 d1 a1
FUNCTION
This function is designed specifically because of the inherent
trickiness of Metas.
Under normal situations, the functionality of this function would be
incorporated into AddAttributes(). Unfortunately, because Metas
are their own classes, the size of the Meta depends on the
definitions held in the defining AttributeTags. Therefore, the Meta
cannot be allocated until it knows the required size, it wouldn't
know the size until the AddAttributes call, but it can't call
AddAttributes until the Meta exists so that the AttributeTable
pointer can be passed in.
At anyrate, this function determines the number of new attribute
there are (returned num) and the additional size that will be
needed (by incrementing the *countptr for each new attribute).
Attributes which are already contained within the super are
cheerfully ignored. Respecified Attributes are assumed to be
attempts to redefine the default value, not to respecify an
attribute's size.
You probably won't need to use this function, unless you are
creating your own Meta or METHODs for Metas.
INPUTS
ATTRIBUTE_TAG tags[]; - optional pointer to a NULL terminated
array of AttributeTags.
long *countptr; - initialized pointer to the long which
will be incremented by the additional
size required by the passed
attributes. If any attributes are
redefined (from the super), the size
will not be incremented for that
attribute.
META *super; - optional pointer to a superclass.
OUTPUTS
long num; - number of new attributes (does not
include attributes redefined from the
passed super.
RESULT
The countptr variable is incremented by the additional size, above
and beyond the size of 'super', that the passed attribute tags would
require.
BUGS
none known.
NOTES
*countptr MUST be initialized, probably to the size of the
superClass, as the size of the superClass is not used in calculating
the size (*countPtr) in this function.
SEE ALSO
AddAttributes()
CopyDefaultAttributes()
FreeAttributes()
FindAttribute()
FindAttrDefn()
NAME
PSem -- procures the semaphore for the given address.
SYNOPSIS
result = PSem( address, flags )
d0 a0 d0
FUNCTION
Copious documentation on the PSem() function is provided for in the
Introduction.doc. Please see it if this AutoDoc does not answer
your questions....
This function semaphores the given address dictated by the
following flags:
SSEM_READ
SSEM_ATTEMPT
SSEM_WRITE
SSEM_LOCK (SSEM_READ | SSEM_WRITE)
In addition, several other flags alter the semaphoring code:
SSEM_VARIABLE 0x8
SSEM_MAX 0x10
SSEM_SUBTRACT 0x80000000
SSEM_DESTROY 0x20
The following macros have been built around PSem() to add
readability:
/*
* Conditional variables
*/
SetCondition(address,number)\
PSem(address, SSEM_VARIABLE | SSEM_READ | ((-number) << 8))
WaitCondition(address,number)\
PSem(address, SSEM_VARIABLE | SSEM_READ | (number << 8))
CreateCondition() PSem((void *)-1, SSEM_VARIABLE)
DestroyCondition(address)\
PSem(address, SSEM_VARIABLE | SSEM_DESTROY)
/*
* Level-triggered semaphores.
*/
WaitLevel(address)\
PSem(address, SSEM_ATTEMPT|SSEM_WRITE);\
PSem(address, SSEM_READ);\
VSem(address)
SetLevel(address)\
VSem(address);
/*
* "Sticky" semaphores
*/
CreateSemaphore(count) PSem((void *)-1, SSEM_MAX | (count << 8))
DestroySemaphore(address) PSem(address, SSEM_DESTROY)
/*
* Couting semaphores of various kinds.
*/
ObtainNumber(address,num) PSem(address, SSEM_READ | (num << 8))
ReleaseNumber(address, num) PSem(address, SSEM_READ | ((-num) << 8))
UpCountSem(address,max) PSem(address, SSEM_READ | SSEM_MAX |\
(max << 8))
DownCountSem(address) VSem(address)
/*
* Locks
*/
WriteLock(address) PSem(address, SSEM_WRITE)
ReadLock(address) PSem(address, SSEM_READ)
RWLock(address) PSem(address, SSEM_READ | SSEM_WRITE)
If anyone else attempts to semaphore the same address (via PSem),
the system takes appropriate action (according to the flags).
if the system cannot allocate a sempahore object internally,
a busy loop with a Delay(30) is used until it can. You
are guaranteed that, when PSem returns, you have a lock o
the semaphore -- unless SSEM_ATTEMPT is used, in which case you must
look at the return code.
INPUTS
void *address; - Any address within the system. (-1) is reserved
as allocating a new semaphore -- that semaphore
address would be returned....
ULONG flags; - some combination of the flags above.
OUTPUTS
void *result; - result code for SSEM_ATTEMPT. Otherwise, returns
semaphore address. This will be equivalent to
the argument "address", or the allocated semaphore
address if "address" is (-1).
The result code for SSEM_ATTEMPT is (1L) for
success and NULL for failure.
RESULT
The specified semaphore action will have taken place.
BUGS
none known.
NOTES
Although it is not strictly necessary, you will undoutedly encounter
bugs if the address on which you have a semaphore is freed before the
semaphore is. Mostly because another task may then allocate that
address, and attempt a semaphore on it -- leading to unexpected
deadly embrace conditions.
The address passed need not point to an object, as the BinTree and
List code require.
SEE ALSO
From exec.library:
ObtainSemaphore()
ObtainSemaphoreShared()
AttemptSemaphore()
VSem()
Introduction.doc
NAME
PSemString -- used to ensure single-thread startup.
SYNOPSIS
result = PSemString( char *string, long semFlags )
a0 d0
FUNCTION
Does the following:
return PSem(UseString(string), semFlags);
The browser uses this function to ensure that only a single
copy of itself is running.
INPUTS
char *string; - the system string equivalent which is used to
semaphore thread startup.
long semFlags; - the flags to send to PSem().
OUTPUTS
void *result; - result code for SSEM_ATTEMPT. Otherwise, returns
semaphore address. This will be equivalent to
the argument "address", or the allocated semaphore
address if "address" is (-1).
The result code for SSEM_ATTEMPT is (1L) for
success and NULL for failure.
RESULT
BUGS
none known.
NOTES
SEE ALSO
VSemString()
PSem()
VSem()
NAME
QuickDropString -- Decrements the useCount of a known system string.
SYNOPSIS
QuickDropString( string )
a2
FUNCTION
This function decrements the useCount of a known system string.
The passed string *must* be a pointer to a system string.
If the useCount drops to zero, DropString is automatically called
in order to delete the string object from the correct place in
the system's string hash table.
Therefore, only call QuickDropString when you think you will have
more than one reference to them. That allows QDS() to work
fastest.
INPUTS
char *string; - the string to lower the refcounts of the system string.
OUTPUTS
RESULT
The given system string has had its useCount decremented.
BUGS
none known.
NOTES
SEE ALSO
UseString()
QuickUseString()
FindString()
DropString()
NAME
QuickUseString -- Increment the usage counter of a system string.
SYNOPSIS
string = QuickUseString( string )
d0 a2
FUNCTION
This function increments the system usage counter for a string
that you already know is a system string. This must be the
*address* of the system string, not a buffer pointer equivalent.
If you pass in a NULL, this function returns a NULL.
You should UseString() whenever saving a suitable string into
a structure -- a matching DropString() will then deallocate the
reference. Under the appropriate conditions (mentioned above)
you may use QuickUseString() to avoid the hash and binary search
calls.
INPUTS
char *string; - the system string whose useCount should be incremented
OUTPUTS
char *string; - the system string.
Exactly what was passed into it!
RESULT
The system string's internal useCount is incremented
BUGS
none known.
NOTES
Don't pass in arbitrary buffer pointers or you may risk overwriting
your stack, or memory.
SEE ALSO
UseString()
FindString()
DropString()
QuickDropString()
NAME
RecurseTree -- Recursively call a function on each BinNode of an
AVLTREE
SYNOPSIS
result = RecurseTree( bt, func, data, recurse )
d0 a0 a1 d0 d1
FUNCTION
This function will recurse through the binary tree, calling func()
for each object found with the parameters 'object key data', where
object is the object in the binary tree, key is the key that the
object is sorted on, and data is the data passed into the Recurse()
call.
If this func() ever returns non-NULL, the recursion is stopped, and
the non_NULL return code is returned to the caller of RecurseTree.
There are three different ways to recurse through a binary tree.
The following flags are defined in shadow/bintree.h:
SHADOW_RECURSE_INORDER == 1
SHADOW_RECURSE_PREORDER == 2
SHADOW_RECURSE_POSTORDER == 3
SHADOW_RECURSE_BACKORDER == 4
The order of the recursion is determined by these flags passed as
the recurse parameter. INORDER outputs the left children, then the
root, then the right children. PREORDER outputs the root, the left,
then the right. POSTORDER outputs the left, the right, then the
root. BACKORDER outputs the right, the root, then the left.
INPUTS
AVLTREE *bt; - the binary tree to recurse
over.
void *(*func)(void *, ULONG, void *) - the function. return value
a0 d0 a1 used below. Return NULL to
continue recursive calling,
non-NULL to end recursive calls.
Three parameters are:
object, key, data.
See above.
void *data - the passed data
long recurse - the recurse type flag.
OUTPUTS
void *result; - returns non-NULL result of func() if func() ever
returns non-NULL. Else returns NULL.
RESULT
func() called for each element in the binary tree.
BUGS
None known.
NOTES
Do NOT RemoveTreeNode() the object from the binary tree that you
are recursing through in the passed function. AND do not call any
methods that would....
Remember that the keys are sorted unsigned, not signed.
SEE ALSO
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode() RemoveWatchedTreeNode()
FreeTreeAllNodes() RemoveWatchedTreeStringNode()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
RemoveAllPatches -- Removes all Patches from a given class.
SYNOPSIS
RemoveAllPatches( meta )
a0
FUNCTION
This function will remove all of the method patches of a given
class. This should be executed when deleting a class in which
methods could be patched.
It is currently called in the META_DESTROY of the metaclass and the
metaCluster.
Because of this, it is IMPOSSIBLE to patch the METH_DESTROY
method for any metas, because they are their own classes -- the
function that would call RemoveALlPatches may be in a method-chain,
which would not be valid when control returned to DSM() to continue
the method chain. This would be confusing, at best.... :(
INPUTS
META meta; - the class to delete all the patches from.
OUTPUTS
RESULT
BUGS
none known.
NOTES
SEE ALSO
DSM() DoShadow()
InvalidateCache()
SetMethodArgs()
AddMethods()
DestroyMethodTable()
FindMethodHandle()
BlockMethod()
SetupMethodTags()
NAME
RemoveAutoResource -- Removes resource from process' tracking tree.
SYNOPSIS
resource = RemoveAutoResource( task, resource, key )
d0 a0 d0 a1
FUNCTION
The resource, which is found using the resource/key pair, is
removed from the process' ATTR_RESOURCETREE and returned back
to your control. No METH_REMOVE is done, and you must
DropObject() the resource which is returned.
Task parameter is optional and defaults to the current task.
Resource parameter is optional, and defaults to whatever
resource is found using the provided key. (If key >255, then
key is assumed to be a string, and is handled accordingly.)
INPUTS
OBJECT task; - The optional task object that performs
the auto-tracking. If not specified,
assumes current taskObject.
OBJECT resource; - The optional object being auto-tracked.
If no resource, then resource is
looked up on the binary tree using
the value in key.
char *key; - The name of the resource. Resources
without names are stored by their
addresses. Name addresses of 0-255
are reserved for priority freeing.
Resources are freed in INCREASING
key order.
OUTPUTS
OBJECT resource; - The resource as found. You must
DropObject() the returned resource
when you are no longer interested in
it. Eventually, you must
RemoveObject() the resource when the
resource is no longer needed
-anywhere-!
RESULT
BUGS
none known.
NOTES
SEE ALSO
AddAutoResource()
DropObject()
NAME
RemoveClassWatcher -- Removes a watcher from all classes.
SYNOPSIS
RemoveClassWatcher( watchName, director, name, class )
a0 a1 d0 d1
FUNCTION
This function will remove the director from the class' attribute
watching SList of the passed name. This is a low-level routine.
You should call the DIRECTOR_CLASS routines instead. See browser.c,
or ShadowLibraryMethods.doc.
INPUTS
char *watchName; - the attribute name that is watched
OBJECT director; - the director to Remove from the
attribute watching SList.
char *name; - the name of the watcher.
META class; - the class to remove the watcher from.
OUTPUTS
none
RESULT
The director is removed from the class' watch list.
BUGS
none known.
NOTES
SEE ALSO
AddWatcherNode()
RemoveWatcherNode()
AddClassWatcher()
NAME
RemoveCurrentProgram -- removes the current process from the system.
SYNOPSIS
RemoveCurrentProgram( semaphore )
a0
FUNCTION
This function is the counterpart of InitOOProgram(). It removes an
AmigaDOS loaded program from the system so that that program can exit
safely.
This is S.O.P. for cleaning up a -program-.
RemoveCurrentProgram() waits for no other process to own a reference
to the process associated with the program. While it does this, it
handles messages on jp_port and jp_replyPort (struct ShadowProcess).
This function sends a METH_REMOVE to the processObject, and waits on
the process' jp_port and jp->replyPort for messages (which it manages
by taking everything off the list, handling the messages, then
checking for more signals). It also waits for a ^C and then checks
that jp_parent is NULL.
A program may create many threads on itself. When INIT'ing a process
object, one parameter that the programmer can pass is a SEMF. This
is a pointer to a semaphore that is passed into the process creation
code. It is ObtainShared() during the process startup, and
Release()'d when the thread is done executing.
RemoveCurrentProgram() waits on this semaphore until all threads
have exited before removing the program's process object.
A NULL semaphore is dealt with appropriately.
INPUTS
struct SignalSemaphore *semaphore; - the thread semaphore
OUTPUTS
RESULT
The program's process object is removed and associated ports freed.
BUGS
none known.
NOTES
SEE ALSO
InitOOProgram()
NAME
RemoveObject -- send a METH_REMOVE to an object.
SYNOPSIS
RemoveObject( OBJECT object )
a0
FUNCTION
Does a:
DoShadow(object, NULL, METH_REMOVE, METHOD_END);
Followed by a:
DropObject(object);
This removes the object from the system lists, and from your local
sequence of execution. You should not refer to "object" after
you pass it into this function unless you have maintained an
additional usage of the object as in:
RemoveObject(UseObject(object);
/*
* I can still use object!
*/
.
.
.
DropObject(object);
INPUTS
OBJECT object; - the object to send the Remove method to.
OUTPUTS
none.
RESULT
BUGS
none known.
NOTES
SEE ALSO
CreateInstance() -- in ShadowLibFuncs.doc
CreateSubClass() -- in ShadowLibFuncs.doc
NAME
RemoveSListNode -- removes a node from a prioritized, singly-linked
list.
SYNOPSIS
result = RemoveSListNode( list, object, name )
d0 a0 a1 d1
FUNCTION
This function removes an object from a singly linked list with the
given name.
INPUTS
SList *list; - a pointer to the list from which to
remove the object.
OBJECT object; - the object to remove.
char *name; - the name it was added as.
OUTPUTS
BOOL result; - result code
returns FALSE if can't find the node to Remove.
RESULT
One fewer nodes are on the list.
BUGS
none known.
NOTES
SEE ALSO
FindNodePriInSList() AddWatchedSListNode()
AddSListNode() RemoveWatchedSListNode()
NAME
RemoveThread -- removes a previously initialized thread.
SYNOPSIS
RemoveThread( object )
a0
FUNCTION
This function is no longer valid under SHADOW V. If you have been
calling it and need directions on how to update your software,
please see both the ShadowLibraryMethods.doc and the
Introduction.doc about the PROCESS_CLASS.
NAME
RemoveTreeNode -- Removes a node from a binary tree
SYNOPSIS
result = RemoveTreeNode( bt, object, key )
d0 a0 a1 d0
FUNCTION
This function will remove an object from the binary tree,
dropping it via DropObject().
The object pointer is required to verify the correct node is
being removed (in case nodes with the same key exist in the
same tree).
INPUTS
AVLTREE *bt; - a pointer to the root of the binary tree.
OBJECT object; - the object to add into the tree.
ULONG key; - the key value to insert on.
OUTPUTS
BOOL result
returns FALSE on failure to remove.
RESULT
The object exists in the tree at least one fewer times than it did.
BUGS
none known.
NOTES
Remember that the keys are sorted unsigned, not signed.
SEE ALSO
DropObject()
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode() RemoveWatchedTreeNode()
FreeTreeAllNodes() RemoveWatchedTreeStringNode()
RecurseTree()
RemoveTreeStringNode()
NAME
RemoveTreeStringNode -- Removes a node from a binary tree.
SYNOPSIS
result = RemoveTreeStringNode( bt, object, name )
a0 a1 d1
FUNCTION
This function will remove an object from the binary tree,
dropping it via DropObject(), and dropping the string
via DropString (if the node is found!).
The object pointer is required to verify that the correct node is
being removed (in case nodes with the same key exist in the same
tree).
INPUTS
AVLTREE *bt; - a pointer to the root of the binary tree.
OBJECT object; - the object to add into the tree.
char *name; - the name to insert on.
OUTPUTS
BOOL result
returns FALSE on failure to remove.
RESULT
The object exists in the tree at least one fewer times than it did.
BUGS
none known.
NOTES
Yes, that's d1, not d0 for 'name' parameter.
SEE ALSO
DropObject DropString
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode() RemoveWatchedTreeNode()
FreeTreeAllNodes() RemoveWatchedTreeStringNode()
RecurseTree()
RemoveTreeNode()
NAME
RemoveWatchedSListNode -- removes a node from a watched, prioritized
singly-linked list.
SYNOPSIS
result = RemoveWatchedSListNode( list, object, name )
d0 a0 a1 d1
FUNCTION
This function removes an object from a watched, singly-linked list
with the given name.
If any parties are interested, WatcherDispatch is called with
W_REMOVE_NODE for the flag parameter.
INPUTS
W_SLIST list; - a pointer to the list from which to
remove the object.
OBJECT object; - the object to remove.
char *name; - the name it was added as.
OUTPUTS
BOOL result; - result code
returns FALSE if can't Remove.
RESULT
One fewer nodes are on the list.
BUGS
none known.
NOTES
SEE ALSO
FindNodePriInSList() AddWatchedSListNode()
AddSListNode()
RemoveSListNode()
NAME
RemoveWatchedTreeNode -- Removes an object from the watched binary
tree.
SYNOPSIS
result = RemoveWatchedTreeNode( bt, object, key )
d0 a0 a1 d0
FUNCTION
This function will remove an object from the watched binary tree,
dropping it via DropObject().
The object pointer is required to verify the correct node is
being removed (in case nodes with the same key exist in the
same tree).
If any parties are interested, WatcherDispatch is called with
W_REMOVE_NODE
INPUTS
W_AVLTREE *bt; - a pointer to the root of the watched
binary tree.
OBJECT object; - the object to add into the tree.
ULONG key; - the key value to insert on.
OUTPUTS
BOOL result
returns FALSE on failure to Remove.
RESULT
The object exists in the tree at least one fewer times than it did.
Remember that the keys are sorted unsigned, not signed.
BUGS
none known.
NOTES
SEE ALSO
DropObject()
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode()
FreeTreeAllNodes() RemoveWatchedTreeStringNode()
RecurseTree()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
RemoveWatchedTreeStringNode -- Removes an object from the given
binary tree
SYNOPSIS
result = RemoveWatchedTreeStringNode( bt, object, name )
d0 a0 a1 d1
FUNCTION
This function will remove an object from the watched binary tree,
dropping it via DropObject(), and dropping the string
via DropString (if node is found!).
The object pointer is required to verify the correct node is
being removed (in case nodes with the same key exist in the
same tree).
If any parties are interested, WatcherDispatch is called with
W_REMOVE_NODE
INPUTS
W_AVLTREE *bt; - a pointer to the root of the watched binary
tree.
OBJECT object; - the object to add into the tree.
char *name; - the name to insert on.
OUTPUTS
BOOL result
returns FALSE on failure to remove.
RESULT
The object exists in the tree at least one fewer times than it did.
BUGS
none known.
NOTES
SEE ALSO
DropObject DropString
AddTreeNode() AddWatchedTreeNode()
AddTreeStringNode() AddWatchedTreeStringNode()
FindTreeNode() RemoveWatchedTreeNode()
FreeTreeAllNodes()
RecurseTree()
RemoveTreeNode()
RemoveTreeStringNode()
NAME
RemoveWatcherNode -- Removes a watcher to the watched variable
SYNOPSIS
result = RemoveWatcherNode( wv, node, name )
a0 a1 d1
FUNCTION
This removes a watcher node from a watched variable. This
is a low-level routine. You should call the DIRECTOR CLASS
routines instead. See browser.c, or ShadowLibMethods.doc.
If any parties are interested, WatcherDispatch is called with
W_REMOVE_WATCHER for the flag parameter.
INPUTS
W_VALUE *wv; - the watched variable being watched.
OBJECT node; - the director to remove from the watch
list.
char *name; - the name of the watcher.
OUTPUTS
BOOL result
returns FALSE if failed to Remove.
RESULT
The director is removed from the watch list.
BUGS
none known.
NOTES
SEE ALSO
AddWatcherNode()
AddClassWatcher()
RemoveClassWatcher()
NAME
ReplaceObject -- Semaphored access to an object in a public area.
SYNOPSIS
oldObject = ReplaceObject(objectPtr ,newObject, oldValue )
d0 a1 d0 d1
FUNCTION
In some attributes, there may be object pointers that you need
to change in that attribute. On the other hand, somebody else
might retrieve it at the same time.
This function uses the ShadowBase->sb_semSemaphore to protect the
access to the objectPtr. The object that is returned is returned
Use()'d, so when you are done with the object you should call
DropObject(object) on it. The old value that was stored at the
objectPtr address is returned as oldObject and replaced by
newObject if, and only if, it is the same as oldValue. Otherwise
newObject is returned.
The newObject is TRANSFERRED to the address, so if you want to
maintain a valid pointer in newObject when ReplaceObject() returns,
call this function like this:
oldObject = ReplaceObject(objectPtr, UseObject(newObject), old);
If you don't care about the returned object, you should call the
function like this:
DropObject(ReplaceObject(objectPtr, newObject, old));
Note: the returned object may, in fact, be newObject, or oldValue --
be sure you know what you're doing!
INPUTS
OBJECT *objectPtr; - the pointer to the structure element that
holds the object pointer you want.
OBJECT newObject; - object to transfer into the objectPtr.
OBJECT oldValue; - the object value that this function will
check for before replacing with newObject.
OUTPUTS
void *object; - either the same as oldValue or, newObject if
*objectPtr doesn't point to oldValue.
RESULT
BUGS
none known.
NOTES
SEE ALSO
GetObject()
SetObject()
NAME
SetMethodArgs -- parses a ArgumentTag structure for method creation.
SYNOPSIS
SetMethodArgs( mh, args )
a0 a1
FUNCTION
This is a system function, you should not need to call it.
However, it does serve to elucidate several issues wrt ARGUMENT_TAG
structures.
This function parses out the ArgumentTag structure.
It sets up the mh_num, mh_size and mh_args field in the
passed MethodHandle structure.
If the function returns a variable that needs to be kept
track of, the last ArgumentTag structure (whose at_tag should be
zero) in the array should contain information for async. method
sends to safely deallocate or otherwise resource track the
returned value.
Valid returns are:
SHADOW_RETURN_BLANK 0
SHADOW_RETURN_OBJECT 1
SHADOW_RETURN_STRING 2
SHADOW_RETURN_PORT 3
SHADOW_RETURN_TAGL 4
SHADOW_RETURN_PTR 5
SHADOW_RETURN_MRFO 6
These values should be stored in the at_size field of the last
ArgumentTag array item..
For SHADOW_RETURN_PTR, the size of the pointer should be stored
in the at_flags field of the same item, for SHADOW_RETURN_TAGL,
the size of each array item should be stored in the at_flags field
of this last item, and for SHADOW_RETURN_MRFO, the offset of the
returned data from the object in question should be placed in the
at_flags field
Normally, the system supports a number of at_tag values:
'MRFO':
used for object values which add at_flags to
the passed object pointer.
at_size should be four
at_flags -- the offset of the passed data from the object ptr.
Note that MRFO exists for system use, however you are free to
use the item as well -- but it's of little to no use, just
pass the object instead!
'JOBJ':
Used for an object.
at_size should be four
at_flags should be one of:
SHADOW_OBJECT
SHADOW_CLASSLESSOBJECT
SHADOW_META
SHADOW_CLASS,
SHADOW_CLUSTER
SHADOW_COMPOSITE
though this is more for peace of mind than necessity.
'JMSG':
Used for a message creted by MessageMaker()
at_size should be four
at_flags should be zero
'JSTR':
Used for a system string.
at_size should be four
at_flags should be zero
'PORT':
Used for a ppipc port.
at_size should be four
at_flags should be ???? <-- anything you like!
'TAGL':
Used for a NULL terminated array.
at_size should be four.
at_flags should be the size of each array item
'RTRN':
reserved by the system, don't use.
'APTR'
a pointer to some memory.
at_size should be four.
at_flags should be zero if you don't want to copy the data to
another block when sending async., or should be the size of
the data pointed to if you do.
Create you own 4 character constant:
at_size should be an even number -- you can pass arbitrarily
large structures on the stack, this way.
at_flags ignored.
INPUTS
struct MethodHandle *mh; - a MethodHandle being initialized.
ARGUMENT_TAG args[]; - the (optional, and NULL-terminated)
ArgumentTag array for this handle.
OUTPUTS
RESULT
mh->mh_args, mh->mh_num, mh->mh_size fields are set up properly.
BUGS
none known.
NOTES
SEE ALSO
DSM() DoShadow()
InvalidateCache()
AddMethods()
DestroyMethodTable()
FindMethodHandle()
BlockMethod()
RemoveAllPatches()
SetupMethodTags()
NAME
SetObject -- Semaphored access to an object in a public area.
SYNOPSIS
oldObject = SetObject(objectPtr , newObject )
d0 a1 d1
FUNCTION
In some attributes, there may be object pointers that you need
to change in that attribute. On the other hand, somebody else
might retrieve it at the same time.
This function uses the ShadowBase->sb_semSemaphore to protect the
access to the objectPtr. The object that is returned is returned
Use()'d, so when you are done with the object you should call
DropObject(object) on it. The old value that was stored at the
objectPtr address is returned as oldObject and replaced by
newObject.
The newObject is TRANSFERRED to the address, so if you want to
maintain a valid pointer in newObject when SetObject() returns,
call this function like this:
oldObject = SetObject(objectPtr, UseObject(newObject));
If you don't care about the returned object, you should call the
function like this:
DropObject(SetObject(objectPtr, newObject));
INPUTS
OBJECT *objectPtr; - the pointer to the structure element that
holds the object pointer you want.
OBJECT newObject; - object to transfer into the objectPtr.
OUTPUTS
void *object; - the object that *objectPtr points to.
RESULT
BUGS
none known.
NOTES
SEE ALSO
GetObject()
ReplaceObject();
NAME
SetShadowError -- Sets an error code for SHADOW
SYNOPSIS
SetShadowError(error, sub_error)
d0 d1
FUNCTION
This function sets the last SHADOW error and suberror that
occurred within the calling process' context to the passed values.
INPUTS
error ; - the error code to set.
sub_error ; - the sub-error code to set.
OUTPUTS
<none>
RESULT
BUGS
none known.
NOTES
SEE ALSO
GetShadowError
NAME
SetupMethodTags -- defines all methods in the MethodTag array as
being run by a certain process object, and
being owned by a certain object.
SYNOPSIS
SetupMethodTags( tags, procObject, defnObject )
a1 d0 d1
FUNCTION
This function will initialize the (required, NULL-terminated) tags
array so that each method is located in a particular defnObject and
wants to be called in a partiular procObject's process.
For instance, gui methods may exist in a libraryObject (ie: a
library) and want to be run by the guiProcObject.
If passed objects of -1, the current task object is used.
[That is; FindTask(NULL)->tc_UserData -- CurrentProcess()]
If any element within the METHOD_TAG has a defnObject already set
(non-NULL), then the defnObject for that element remains as before.
Similarly for the procObject field.
INPUTS
METHOD_TAG tags[]; - NULL-terminated MethodTag array.
OBJECT procObject; - the process object in which to run
the methods.
OBJECT defnObject; - the object that "contains" the
definition of the ArgumentTag -and-
the function code.
OUTPUTS
RESULT
BUGS
none known.
NOTES
This is what guarantees that the function and ArgumentTag pointers
remain valid as long as a method could call that function.
The ArgumentTag structure is NOT copied when stored into the
MethodHandler structure (the information in MethodTags and
AttributeTags is).
This function does not produce valid results for methods that are
defined as METH_FLAG_CLASS or METH_FLAG_PORT or METH_FLAG_SPEC.
You will have to fill in the procObject field for these
method-types yourself.
SetupMethodTags() only affects procObject and defnObject fields
that are NULL.
SEE ALSO
DSM() DoShadow()
InvalidateCache()
SetMethodArgs()
AddMethods()
DestroyMethodTable()
FindMethodHandle()
BlockMethod()
RemoveAllPatches()
NAME
UseObject -- resource tracking for shadow objects.
SYNOPSIS
object = UseObject( object )
d0 a0
FUNCTION
This function increments the object's cob_useCount field.
You should Use an object whenever you save a pointer into
a structure.
INPUTS
OBJECT object; - the object to effect the change upon.
If NULL, nothing happens
OUTPUTS
OBJECT object; - the same as the object sent in.
RESULT
object's cob_object is incremented.
BUGS
none known.
NOTES
SEE ALSO
DropObject()
NAME
UseString -- gets a system-wide address for a given string.
SYNOPSIS
string = UseString( buffer )
d0 a2
FUNCTION
Shadow uses a system very much similar to the NeXT's -- a system-
wide repository for statis-string addresses.
Strings are hashed into a 1024 table entry and chained onto sorted
binary trees. The string which is returned is guaranteed to be a
unique string address for the passed buffer.
The passed buffer's address is *NOT* used as the system string
address, so it can be a temporary stack-allocated buffer. The
system string is created when a first UseString() is called for
a given buffer. On the second UseString() call for the same buffer,
the same string address will be returned, and an internal counter
which tracks the string usage is incremented.
These system strings may *NOT* be mangled, they are read-only.
They are particularly good for static data that you wish to do
searches on, as system-strings have a unique address, strcmp() is
unnecessary, merely compare the string addresses. They are used
internally for BinNode strings, method names, attribute names,
class names, etc.
INPUTS
char *buffer; - the string to retrieve a unique system pointer for.
Given a NULL input, will return NULL.
OUTPUTS
char *string; - the unique string as returned by the system. A NULL
signals an error.
RESULT
Either a new system string is created, and the buffer copied into
it, or an old system string is retrieved and its usage counter
incremented.
BUGS
none known.
NOTES
The buffer should be word-aligned for faster access and long-word
aligned for fastest access.
SEE ALSO
QuickUseString()
FindString()
DropString()
QuickDropString()
NAME
VSem -- Vacate a semaphore
SYNOPSIS
VSem( address )
a0
FUNCTION
This function does the equivalent of a ReleaseSemaphore on the
given address.
Every PSem() should be matched with a VSem(), except for PSem()s
where an SSEM_ATTEMPT failed (returned NULL, in which case VSem()
should NOT be called.
INPUTS
void *address; - Any address in the system.
OUTPUTS
RESULT
The semaphore will be released (vacated), and the semaphore object
freed if no longer needed.
BUGS
none known.
NOTES
If no semaphore with that address can be found, nothing happens.
But this case may a bug in the user program as you shoudn't
be freeing semaphores no one has allocated....
SEE ALSO
From exec.library:
ReleaseSemaphore()
PSem()
Introduction.doc
NAME
VSemString -- used to ensure single-threaded startup.
SYNOPSIS
VSemString( char *string )
a0
FUNCTION
Does the following:
VSem(FindString(string), semFlags);
DropString(string);
The browser uses this function to ensure that only a single
copy of itself is running.
INPUTS
char *string; - the system string equivalent which is used to
semaphore thread startup.
OUTPUTS
none.
RESULT
BUGS
none known.
NOTES
SEE ALSO
PSemString()
PSem()
VSem()
NAME
WaitThread -- synchronizes thread startup.
SYNOPSIS
task = WaitThread( )
d0
FUNCTION
This function is no longer valid under SHADOW V. If you have been
calling it and need directions on how to update your software,
please see both the ShadowLibraryMethods.doc and the
Introduction.doc about the PROCESS_CLASS.
NAME
WatcherDispatch -- Dispatches all notification methods.
SYNOPSIS
WatcherDispatch( flag, wv, first, second )
d0 a0 a1 d1
FUNCTION
This function dispatches notification to all parties that
have added themselves either to the WatchedVariable in
question, or to the SList that wv->wv_firstClass points to.
Watched Values are a tricky subject which will require a lot
more than a simple AutoDoc note to explain them.
Please see examples in browser.c for now, or refer to the
DIRECTOR_CLASS documentation in ShadowLibMethods.doc and
Introduction.doc.
INPUTS
long flag; - Informs of the type of change made to the value:
W_CHANGE_ZERO 1
W_CHANGE_NON_ZERO 2
W_INSERT_WATCHER 40
W_REMOVE_WATCHER 24
W_INSERT_NODE 32
W_REMOVE_NODE 16
W_VALUE *wv; - the watchedValue that was changed.
void *first; - the object that was added to the list/AVLTREE, or
the value that the variable was changed to.
void *second; - the name or key for the new node in the list/AVLTREE
OUTPUTS
RESULT
All interested parties are informed of the change.
BUGS
none known.
NOTES
SEE ALSO
AddWatcherNode()
AddClassWatcher()